//泛型

/**
 * 数据结构 - 描述和组织数据
 * 常见的时间复杂度(从小到大) - O(1)  O(logN)  O(N)  O(NlogN)  O(N^2)
 */
//泛型 - 对类型进行参数化，<T>:指定类型
//泛型存在的两个最大的意义：【编译时就完成了以下两步骤，检查和转换后擦除，泛型主要是编译时期的一种机制【擦除机制】，运行时是没有泛型的概念的】
//1、存放元素的时候，会进行类型的检查
//2、取出元素的时候，不需要进行类型的强转。
/**
 * 擦出机制：编译时将T全部擦除成Object
 */
// 泛型类 泛型方法
//泛型的上界
//通配符
//包装类

class Message<T>{
    private T message;

    public T getMessage() {
        return message;
    }

    public void setMessage(T message) {
        this.message = message;
    }
}
class Test2{
    public static void func(Message<?> temp){//通配符
        System.out.println(temp.getMessage());
    }
    public static void main(String[] args) {
        Message<String> m = new Message<>();
        m.setMessage("来喽");
        func(m);

       /* String ret = m.getMessage();
        System.out.println(ret);*/
        System.out.println(m.getMessage());

        Message<Integer> m1 = new Message<>();
        m1.setMessage(10);
        func(m1);
        /*Integer ret1 = m1.getMessage();
        System.out.println(ret1);*/
        System.out.println(m1.getMessage());


    }
   /* public static void func(Message<Integer> temp){
        System.out.println(temp.getMessage());
    }*/
}

/**
 * 实现一个类，类中包含一个数组成员，使得数组中可以存放任何类型的数据，也可以根据成员方法返回数组中某个下标的值
 */
/**
 * 泛型类
 * @param <T> : 占位符，表示当前类是一个泛型类，T在之后可以替换为任意类类型，用来指定类型
 */
class MyArray1<T>{
    public T[] obj =(T[])new Object[10];
    public void setValue(int pos,T value){
        obj[pos] = value;
    }
    public T getPos(int pos){
        return obj[pos];
    }

}
class Test1{
    public static void main(String[] args) {
        MyArray1<Integer> myArray1 = new MyArray1<Integer>();
        myArray1.setValue(0,1);
        myArray1.setValue(1,5);
        int a = myArray1.getPos(1);
        System.out.println(a);
        MyArray1<String> myArray2 = new MyArray1<>();
        myArray2.setValue(1,"hello");
        myArray2.setValue(2,"hh");
        String s = myArray2.getPos(1);
        System.out.println(s);
    }

}

//下面这种方法的缺点：
//1、存放元素的时候，任何类型的数据都可以存放
//2、取出元素的时候，得自己判断【强转】
    //于是出现了泛型，将类型参数化，用哪种类型时就用哪种
class MyArray{
   public Object[] obj = new Object[10];
   public void setVal(int pos,Object value){
       obj[pos] = value;
   }
   public Object getPos(int pos){
       return obj[pos];
   }

}
public class Test {
    public static void main3(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setVal(0,10);
        myArray.setVal(1,"hello");
        String s = (String)myArray.getPos(1);
    }
    /**
     * 1、用Object数组 - error【Java中，数组比较特殊，数组是Object类型时不能向下转型，单个类是可以转的，针对数组】
     */
    public static void main1(String[] args) {
        Object[] array = {1,2,3,"hello"};
        //Integer[] array1 = (Integer[]) array;//虽然现在没报错，但运行后还是会报错的
        //即使Object数组 中全是int类型的数据，也会报错，在这里不允许向下类型转换，因为转换时
        //我们并不知道类型是否匹配。
        //String[] array2 = new Object[3];
       // String[] array2 = (String[]) new Object[3];//虽然现在没报错，但运行后还是会报错的

    }
}
